﻿
using System.APMServer.DBModel;
using System.Threading.Channels;

using GCC.Container.Abstracts;

namespace System.APMServer
{
    internal class TraceManager
    {
        public static TraceManager Instance = new();
        public IFreeSql? _dbInstance;
        private readonly Channel<TraceItem> _itemChannel = Channel.CreateUnbounded<TraceItem>();
        private TraceManager() { }
        private AbsGCCLogger? _logger;
        public void Init(AbsGCCLoggerProvider provider)
        {
            _logger = provider.CreateLogger<TraceManager>();
            _dbInstance = GCCEntrance.DBManager!.LocalDB;
        }


        public void Start()
        {
            if (_dbInstance is null)
            {
                return;
            }
            _ = Task.Factory.StartNew(async () =>
            {
                var reader = _itemChannel.Reader;
                while (true)
                {
                    var asd = await reader.WaitToReadAsync();
                    var count = reader.Count;
                    var items = new List<TraceItem>();
                    while (items.Count < count)
                    {
                        items.Add(await reader.ReadAsync());
                    }
                    try
                    {
                        _ = _dbInstance.Insert(items).ExecuteAffrows();
                    }
                    catch (Exception ex)
                    {
                        _logger?.Error($"Save trace data to db error.", exception: ex);
                        continue;
                    }
                }

            }, TaskCreationOptions.LongRunning);
            _logger?.Information("ApmServer init completed.");

        }

        public bool PushItem(TraceItem item)
        {
            if (_dbInstance is null)
            {
                return false;
            }
            return _itemChannel.Writer.TryWrite(item);
        }

        public List<TraceItem> GetByMinTime(long created)
        {
            if (_dbInstance is null)
            {
                return new List<TraceItem>();
            }
            return _dbInstance.Select<TraceItem>()
                .Where(item => item.Created >= created).Take(300).ToList();
        }
    }
}
